package com.bxl.netty.simulator.server;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;

/**
 * <>
 *
 * @author baixl
 * @date 2021/3/18
 */
public class MsgRead {

    int index = 0;
    int length = 0;
    byte[] bytes = null;
    boolean isNew = true;
    ByteBuffer lengthBuffer = null;

    public SocketChannel read(SelectionKey key) {
        SocketChannel channel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int count = 0;
        try {
            while ((count = channel.read(buffer)) > 0) {

                buffer.flip();//发送或获取数据，设置好数据后都要调用此方法
                if(isNew){
                    if(lengthBuffer == null){
                        lengthBuffer =  ByteBuffer.allocate(4);
                    }
                    int  minLength = Math.min(buffer.remaining(),lengthBuffer.remaining());
                    byte[] tempByte = new byte[minLength];
                    buffer.get(tempByte,0,tempByte.length);
                    lengthBuffer.put(tempByte);
                    if(lengthBuffer.remaining() == 0){
                        lengthBuffer.flip();
                        length = lengthBuffer.getInt();
                        index = 0;
                        //获取报文长度
                        isNew = false;
                        bytes = new byte[length];
                        lengthBuffer.clear();
                    }
                }
                
                while (buffer.remaining() > 0) {
                    //可读小于报文长度，读取所有
                    if (buffer.remaining() < (length - index)) {
                        int remaining = buffer.remaining();
                        buffer.get(bytes, index, buffer.remaining());
                        index = index + remaining;
                    } else {
                        //可读大于报文长度，读取报文长度
                        buffer.get(bytes, index, length - index);
                        System.out.println(Thread.currentThread().getName() + ":" + new String(bytes, "UTF-8"));
                        write(channel, "hell world ");
                        //只要不取消，就可以一直读取（不用每次都注册）。同一个channel注册到不同的select，key是不一样的。
                        //key.cancel();
                        isNew = true;
                        if(lengthBuffer == null){
                            lengthBuffer =  ByteBuffer.allocate(4);
                        }
                        int  minLength = Math.min(buffer.remaining(),lengthBuffer.remaining());
                        byte[] tempByte = new byte[minLength];
                        buffer.get(tempByte,0,tempByte.length);
                        lengthBuffer.put(tempByte);
                        if(lengthBuffer.remaining() == 0){
                            lengthBuffer.flip();
                            length = lengthBuffer.getInt();
                            index = 0;
                            //获取报文长度
                            isNew = false;
                            bytes = new byte[length];
                            lengthBuffer.clear();
                        }

                    }
                }

            }
            key.attach(this);
            //register(channel,SelectionKey.OP_READ);
        } catch (IOException e) {
            e.printStackTrace();
            try {
                channel.close();
            } catch (IOException e1) {

            }
        }
        return channel;
    }

    public static SocketChannel write(SocketChannel channel, String msg) {
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        StringBuilder sb = new StringBuilder();
        sb.append("HTTP/1.1 200 OK\r\n")
                .append("Content-Type: text/html;charset=utf-8\r\n")
                .append("\r\n").append(Thread.currentThread().getName()).append("\r\n")
                .append(msg).append("\r\n");
        try {
            buffer.put(sb.toString().getBytes());
            buffer.flip();
            channel.write(buffer);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return channel;
    }
}
